﻿/*****************************************介绍*****************************************
 * 作者：Ywh
 * 创建时间：2024-05-28 15:26:41
 * 功能：音效管理器
 *      1、管理背景音乐
 *      2、管理其他音效
**************************************************************************************/

using System.Collections.Generic;
using UnityEngine;

namespace Game.Framework
{
    [InternalModule(6)]
    public class AudioManager : BaseManager<AudioManager>, IModule
    {
        private const string Pool = "AudioPool";
        private GameObject m_ItemTemp, m_AudioManager;
        private AudioSource m_Bg;
        private List<AudioSource> m_Audios;
        private float m_BgVolume = 1;
        private float m_AudioVolume = 1;
        private Dictionary<string, AudioClip> m_AudioClips;

        private AudioManager()
        {
            m_AudioClips = new Dictionary<string, AudioClip>();
        }

        private void Update()
        {
            for (int i = m_Audios.Count - 1; i >= 0; i--)
            {
                if (!m_Audios[i].isPlaying)
                {
                    PoolManager.Instance.Delete(Pool, m_Audios[i].gameObject);
                    m_Audios.RemoveAt(i);
                }
            }
        }

        private AudioSource CreateAudioSource()
        {
            var obj = PoolManager.Instance.Get(Pool);
            obj.transform.SetParent(m_AudioManager.transform);
            return obj.GetComponent<AudioSource>();
        }

        private void Play(AudioSource source, AudioClip clip, bool isLoop, float volume)
        {
            source.clip = clip;
            source.loop = isLoop;
            source.volume = volume;
            source.Play();
        }

        private AudioClip GetClip(string clipFullName)
        {
            if (string.IsNullOrWhiteSpace(clipFullName)) return null;
            if (!m_AudioClips.TryGetValue(clipFullName, out var clip))
            {
                clip = Resources.Load<AudioClip>(clipFullName);
                if (clip == null)
                {
                    LogManager.LogWarning($"Resources下不存在：{clipFullName}文件，请检查！！", "音效管理");
                    return null;
                }
                m_AudioClips.Add(clipFullName, clip);
            }
            return clip;
        }

        #region 背景音乐

        public void PlayBg(string clipFullName)
        {
            LogManager.Log($"name:{clipFullName}", "音效管理", "播放背景音乐");
            var clip = GetClip(clipFullName);
            if (clip != null)
                PlayBg(clip);
        }

        public void PlayBg(AudioClip clip)
        {
            if (m_Bg == null)
            {
                m_Bg = CreateAudioSource();
                m_Bg.name = "Bg";
            }
            m_Bg.transform.localPosition = Vector3.zero;
            m_Bg.spatialBlend = 0;
            Play(m_Bg, clip, true, m_BgVolume);
        }

        public void PlayBg(AudioClip clip, Vector3 pos)
        {
            if (m_Bg == null)
            {
                m_Bg = CreateAudioSource();
                m_Bg.name = "Bg";
            }
            m_Bg.transform.localPosition = pos;
            m_Bg.spatialBlend = 1;
            Play(m_Bg, clip, true, m_BgVolume);
        }

        public void PauseBg()
        {
            LogManager.Log($"暂停播放", "音效管理", "播放背景音乐");
            if (m_Bg == null) return;
            m_Bg.Pause();
        }

        public void UnPauseBg()
        {
            LogManager.Log($"恢复播放", "音效管理", "播放背景音乐");
            if (m_Bg == null) return;
            m_Bg.UnPause();
        }

        public void StopBg()
        {
            if (m_Bg == null) return;
            m_Bg.Stop();
        }

        public void ChangeBgVolume(float volume)
        {
            m_BgVolume = volume;
            if (m_Bg == null) return;
            m_Bg.volume = volume;
        }

        #endregion

        #region 音效

        public AudioSource PlayAudio(string clipFullName, bool isLoop = false)
        {
            LogManager.Log($"name:{clipFullName} isLoop:{isLoop}", "音效管理", "播放音效");
            var clip = GetClip(clipFullName);
            if (clip == null) return null;
            return PlayAudio(clip, isLoop);
        }

        public AudioSource PlayAudio(AudioClip clip, bool isLoop = false)
        {
            var audio = CreateAudioSource();
            audio.transform.position = Vector3.zero;
            audio.spatialBlend = 0;
            Play(audio, clip, isLoop, m_AudioVolume);
            m_Audios.Add(audio);
            return audio;
        }

        public AudioSource PlayAudio(AudioClip clip, Vector3 pos, bool isLoop = false)
        {
            var audio = CreateAudioSource();
            audio.transform.position = pos;
            audio.spatialBlend = 1;
            Play(audio, clip, isLoop, m_AudioVolume);
            m_Audios.Add(audio);
            return audio;
        }

        public void PauseAudio()
        {
            LogManager.Log($"暂停播放", "音效管理", "播放音效");
            if (m_Audios == null) return;
            foreach (var item in m_Audios)
            {
                item.Pause();
            }
        }
        public void UnPauseAudio()
        {
            LogManager.Log($"恢复播放", "音效管理", "播放音效");
            if (m_Audios == null) return;
            foreach (var item in m_Audios)
            {
                item.UnPause();
            }
        }
        public void StopAudio()
        {
            if (m_Audios == null) return;
            foreach (var item in m_Audios)
            {
                item.Stop();
            }
        }
        public void ChangeAudioVolume(float volume)
        {
            m_AudioVolume = volume;
            if (m_Audios == null) return;
            foreach (var item in m_Audios)
            {
                item.volume = volume;
            }
        }

        #endregion

        private InitResult m_InitResult;

        void IModule.Init()
        {
            m_InitResult = new InitResult(E_ResultType.Waiting);
            m_AudioManager = new GameObject(GetType().Name);
            Object.DontDestroyOnLoad(m_AudioManager);

            m_ItemTemp = new GameObject("Item", typeof(AudioSource));
            m_ItemTemp.transform.SetParent(m_AudioManager.transform);
            PoolManager.Instance.CreatePool(Pool, m_ItemTemp, 64);
            m_Audios = new List<AudioSource>(64);

            EventCenter.Instance.AddEventListen(EventName.MonoUpdate, Update);
            m_InitResult.type = E_ResultType.Success;
        }

        InitResult IModule.GetInitResult() => m_InitResult;

        void IModule.Clear()
        {
            StopBg();
            StopAudio();
            m_Audios.Clear();
            if (m_AudioManager != null)
                Object.Destroy(m_AudioManager);
            m_AudioManager = null;
            EventCenter.Instance.RemoveEventListen(EventName.MonoUpdate, Update);
        }
    }
}